package com.main.beatit;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.*;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.*;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.*;
import android.widget.ImageView.ScaleType;

@SuppressLint({ "NewApi", "WorldReadableFiles" })
public class Patterns extends Activity {
	final int btnPatterns = 9000; // View ID
	final int btnImport = 9001;
	final int btnExtract = 9002;
	final int btnPads = 9003;
	final int layID = R.id.btn1;
	final int patternID = 9050;

	private Intent iFileList;

	Display display; // Device display information
	int displayWidth;
	int displayHeight;
	public static boolean bDraw = false; // Is pattern drew?
	public static int nNowPattern; // I draw this pattern.
	public static boolean bImported = false; // Is pattern imported?
	public static boolean bExtracted = false; // Is pattern imported?

	public static String sImportedFileName;
	public static String sExtractedFileName;
	public static List<String> btiItems = new ArrayList<String>();

	// Pattern View Layout
	LinearLayout llLeftBackground;
	LinearLayout llRightBackground;
	LinearLayout llButton;
	LinearLayout[] llHorizontal;
	public static LinearLayout[][] llPads;
	TextView[] tvPads;
	ImageView[] ivButtons;
	public static TextView tvNowPattern;
	String[] sSoundName = { "CymbalCrash", "HiHatClose", "HiHatOpen", "HiHatPedal", "Kick", "Snare", "Clap", "Cowbell",
			"Rimshot", "TomFloor", "TomMiddle", "CymbalRide", "Shaker", "Tambourine", "Vibraslap", "Hit" };

	public static boolean bViewPatterns; // Is all pattern view?

	public float fOldX = 0;

	int nBackgroundWidth; // Background layout width

	// All Pattern View
	LinearLayout llSecondBackground;
	LinearLayout[] llSecondHorizontal;
	public static LinearLayout[][] llPatterns;
	static TextView tvPatternNum[][];
	static boolean bDeleteMode = false;
	int nWillDelete = -1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.patterns);

		// I don't use auto sleep mode.
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		// Get a display information.
		display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

		displayWidth = display.getWidth();
		displayHeight = display.getHeight();

		iFileList = new Intent(this, FileList.class);

		// Make a view - About pad layout
		llPads = new LinearLayout[8][16];
		llHorizontal = new LinearLayout[8];
		tvPads = new TextView[8];
		ivButtons = new ImageView[4];
		tvNowPattern = new TextView(this);

		// Initialize
		sImportedFileName = "";
		sExtractedFileName = "";
		bDraw = true;
		bViewPatterns = false;
		nNowPattern = 0;
		nBackgroundWidth = displayWidth - ((displayWidth / 5) - 32);

		for (int i = 0; i < 8; i++) {
			tvPads[i] = new TextView(this);
			tvPads[i].setText(sSoundName[i]);
		}

		tvNowPattern.setText((nNowPattern + 1) + " / 16");
		tvNowPattern.setTextSize(displayHeight / 10);
		tvNowPattern.setTextColor(Color.argb(100, 255, 255, 255));

		llLeftBackground = new LinearLayout(this);
		llLeftBackground.setBackgroundColor(Color.BLACK);
		llLeftBackground.setOrientation(LinearLayout.VERTICAL);
		addContentView(llLeftBackground, new LinearLayout.LayoutParams(nBackgroundWidth / 2, displayHeight,
				Gravity.CENTER));

		llRightBackground = new LinearLayout(this);
		llRightBackground.setBackgroundColor(Color.BLACK);
		llRightBackground.setOrientation(LinearLayout.VERTICAL);
		llRightBackground.setX(nBackgroundWidth / 2);
		addContentView(llRightBackground, new LinearLayout.LayoutParams(nBackgroundWidth / 2, displayHeight,
				Gravity.CENTER));

		llButton = new LinearLayout(this);
		llButton.setBackgroundColor(Color.BLACK);
		llButton.setOrientation(LinearLayout.VERTICAL);
		llButton.setX(nBackgroundWidth);
		addContentView(llButton, new LinearLayout.LayoutParams(displayWidth / 5 - 32, displayHeight, Gravity.CENTER));

		for (int i = 0; i < 8; i++) {
			llHorizontal[i] = new LinearLayout(this);
			llHorizontal[i].setBackgroundColor(Color.argb(0, 255, 255, 255));
			llHorizontal[i].setOrientation(LinearLayout.HORIZONTAL);
			llHorizontal[i].setY((displayHeight / 8) * i);
			addContentView(llHorizontal[i], new LinearLayout.LayoutParams(nBackgroundWidth, (displayHeight / 8),
					Gravity.CENTER));
			llLeftBackground.addView(tvPads[i]);
			tvPads[i].setGravity(Gravity.CENTER_VERTICAL);
			tvPads[i].setHeight((displayHeight / 8));
			tvPads[i].setTextColor(Color.argb(100, 255, 255, 255));

			// Make a pad layout.
			for (int j = 0; j < 16; j++) {
				llPads[i][j] = new LinearLayout(this);
				if (j % 4 == 0) {
					llPads[i][j].setBackgroundColor(Color.argb(80, 255, 255, 255));
				} else {
					llPads[i][j].setBackgroundColor(Color.argb(50, 255, 255, 255));
				}
				llHorizontal[i].addView(llPads[i][j]);
				llPads[i][j].setId(layID + (i * 100) + j); // ID : R.id.btn1 +
				// Pad number + Beat
				// number

				// Modify pad layout properties
				LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) llPads[i][j].getLayoutParams();
				lp.bottomMargin = 1;
				lp.topMargin = 1;
				lp.leftMargin = 1;
				lp.rightMargin = 1;
				lp.width = (displayWidth - (displayWidth / 5)) / 16;
				lp.height = displayHeight / 8;
				llPads[i][j].setLayoutParams(lp);

				llPads[i][j].setClickable(true);

				llPads[i][j].setOnClickListener(new View.OnClickListener() {

					public void onClick(View v) {
						int offset = v.getId() - layID;

						// Write or remove pattern
						if ((MainActivity.nPatterns[nNowPattern][offset % 100] & MainActivity.DIGITS[offset / 100]) == 0) {
							MainActivity.nPatterns[nNowPattern][offset % 100] += MainActivity.DIGITS[offset / 100];
						} else {
							MainActivity.nPatterns[nNowPattern][offset % 100] -= MainActivity.DIGITS[offset / 100];
						}

						// Draw pattern view
						drawPatterns(nNowPattern);
					}
				});

				llPads[i][j].setOnTouchListener(new OnTouchListener() {

					public boolean onTouch(View v, MotionEvent event) {

						// If touch a pad layout
						if (event.getAction() == MotionEvent.ACTION_DOWN) {

							fOldX = event.getX();
						} else if (event.getAction() == MotionEvent.ACTION_UP) {

							if (Math.abs(fOldX - event.getX()) >= displayWidth / 8) {
								if (fOldX < event.getX()) {
									int z = 0;
									while (z++ < 16) {
										if (--nNowPattern < 0) {
											nNowPattern = 15;
										}
										if (MainActivity.bEnablePatterns[nNowPattern] == true) {
											drawPatterns(nNowPattern);

											break;
										}
									}
								} else {
									int z = 0;
									while (z++ < 16) {
										if (++nNowPattern > 15) {
											nNowPattern = 0;
										}
										if (MainActivity.bEnablePatterns[nNowPattern] == true) {
											drawPatterns(nNowPattern);

											break;
										}
									}
								}
							}
						}

						return false;
					}
				});

			}

		}

		// For pattern index information layout
		llRightBackground.addView(tvNowPattern);

		drawPatterns(nNowPattern);

		bDraw = true;

		// Make a view - Menu button
		for (int i = 0; i < 4; i++) {
			ivButtons[i] = new ImageView(this);
			switch (i) {
				case 2:
					ivButtons[i].setBackgroundResource(R.drawable.patterns);
					ivButtons[i].setId(btnPatterns);
					break;
				case 0:
					ivButtons[i].setBackgroundResource(R.drawable.imported);
					ivButtons[i].setId(btnImport);
					break;
				case 1:
					ivButtons[i].setBackgroundResource(R.drawable.extract);
					ivButtons[i].setId(btnExtract);
					break;
				case 3:
					ivButtons[i].setBackgroundResource(R.drawable.pads);
					ivButtons[i].setId(btnPads);
					break;
			}
			ivButtons[i].setLayoutParams(new RelativeLayout.LayoutParams((displayWidth / 5) - 32, displayHeight / 4));

			llButton.addView(ivButtons[i]);
			ivButtons[i].setClickable(true);
			ivButtons[i].setScaleType(ScaleType.FIT_CENTER);

			ivButtons[i].setOnTouchListener(new OnTouchListener() {

				public boolean onTouch(View v, MotionEvent event) {
					bDeleteMode = false;

					switch (v.getId()) {
						case btnPatterns:
							if (event.getAction() == MotionEvent.ACTION_DOWN && bViewPatterns == false) {
								// View all pattern
								v.setBackgroundResource(R.drawable.patterns_push);

								openAllPatterns();
								bViewPatterns = true;
							} else if (event.getAction() == MotionEvent.ACTION_DOWN && bViewPatterns == true) {
								// View one pattern
								v.setBackgroundResource(R.drawable.patterns);

								closeAllPatterns(-1);
								bViewPatterns = false;
							}
							break;
						case btnImport:
							if (event.getAction() == MotionEvent.ACTION_DOWN) {
								// I'll import patterns
								v.setBackgroundResource(R.drawable.imported_push);

								startActivity(iFileList);
							} else if (event.getAction() == MotionEvent.ACTION_UP) {
								v.setBackgroundResource(R.drawable.imported);
							}
							break;
						case btnExtract:
							if (event.getAction() == MotionEvent.ACTION_DOWN) {
								// I'll extract patterns
								v.setBackgroundResource(R.drawable.extract_push);

								ExtractDialog dialog = new ExtractDialog(Patterns.this);
								dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {

									public void onDismiss(DialogInterface dialog) {

										if (bExtracted == true) {
											extractPatterns(sExtractedFileName, (int) MainActivity.fBPM);

											bExtracted = false;
										}

										findViewById(btnExtract).setBackgroundResource(R.drawable.extract);
									}
								});
								dialog.show();

							}
							break;
						case btnPads:
							if (event.getAction() == MotionEvent.ACTION_DOWN) {
								v.setBackgroundResource(R.drawable.pads_push);
							} else if (event.getAction() == MotionEvent.ACTION_UP) {
								v.setBackgroundResource(R.drawable.pads);

								onBackPressed();
							}
							break;
					}

					return false;
				}
			});
		}

		// All Pattern View
		llSecondBackground = new LinearLayout(this);
		llPatterns = new LinearLayout[4][4];
		llSecondHorizontal = new LinearLayout[4];
		AbsoluteLayout alTemp = new AbsoluteLayout(this);

		llSecondBackground.setBackgroundColor(Color.BLACK);
		llSecondBackground.setOrientation(LinearLayout.VERTICAL);
		addContentView(llSecondBackground, new LinearLayout.LayoutParams(nBackgroundWidth, displayHeight,
				Gravity.CENTER));

		addContentView(alTemp, new LinearLayout.LayoutParams(nBackgroundWidth, displayHeight, Gravity.CENTER));

		for (int i = 0; i < 4; i++) {
			llSecondHorizontal[i] = new LinearLayout(this);
			llSecondHorizontal[i].setBackgroundColor(Color.argb(0, 255, 255, 255));
			llSecondHorizontal[i].setOrientation(LinearLayout.HORIZONTAL);

			llSecondBackground.addView(llSecondHorizontal[i]);
			llSecondHorizontal[i].setVisibility(View.INVISIBLE);
		}

		llSecondBackground.setVisibility(View.INVISIBLE);
		tvPatternNum = new TextView[4][4];

		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				llPatterns[i][j] = new LinearLayout(this);
				llPatterns[i][j].setBackgroundResource(R.drawable.pattern_on);
				llSecondHorizontal[i].addView(llPatterns[i][j]);
				llPatterns[i][j].setId(patternID + (i * 4 + j));
				tvPatternNum[i][j] = new TextView(this);
				tvPatternNum[i][j].setText("" + (i * 4 + j + 1));
				tvPatternNum[i][j].setTextSize(displayHeight / 15);
				tvPatternNum[i][j].setGravity(Gravity.CENTER);
				llPatterns[i][j].addView(tvPatternNum[i][j]);
				llPatterns[i][j].setGravity(Gravity.CENTER);
				llPatterns[i][j].setClickable(true);

				LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) llPatterns[i][j].getLayoutParams();
				lp.bottomMargin = 2;
				lp.topMargin = 2;
				lp.leftMargin = 2;
				lp.rightMargin = 2;
				lp.width = (displayWidth - (displayWidth / 5)) / 4;
				lp.height = displayHeight / 4;
				llPatterns[i][j].setLayoutParams(lp);

				llPatterns[i][j].setOnClickListener(new View.OnClickListener() {

					public void onClick(View v) {
						if (bDeleteMode == false) {
							// Enable or disable patterns to play.
							if (MainActivity.bEnablePatterns[v.getId() - patternID] == true) {
								if (bViewPatterns == true) {
									bViewPatterns = false;
									closeAllPatterns(v.getId() - patternID);
									findViewById(btnPatterns).setBackgroundResource(R.drawable.patterns);
								}
							} else if (MainActivity.nTotalPattern == v.getId() - patternID) {
								MainActivity.bEnablePatterns[MainActivity.nTotalPattern] = true;
								MainActivity.nTotalPattern++;

								drawAllPatterns();
							}
						} else {
							if (nWillDelete == v.getId() - patternID) {
								for (int i = v.getId() - patternID; i < MainActivity.nTotalPattern; i++) {
									if (i < MainActivity.nTotalPattern - 1) {
										for (int j = 0; j < 16; j++) {
											MainActivity.nPatterns[i][j] = MainActivity.nPatterns[i + 1][j];
										}
									}
								}

								for (int i = MainActivity.nTotalPattern; i < 16; i++) {
									for (int j = 0; j < 16; j++) {
										MainActivity.nPatterns[i][j] = 0;
									}
								}

								MainActivity.nTotalPattern--;
								MainActivity.bEnablePatterns[MainActivity.nTotalPattern] = false;

								drawAllPatterns();

								if (MainActivity.nTotalPattern < 16) {
									llPatterns[MainActivity.nTotalPattern / 4][MainActivity.nTotalPattern % 4]
											.setVisibility(View.INVISIBLE);
								}

								nWillDelete = -1;
							} else {
								for (int i = 0; i < MainActivity.nTotalPattern; i++) {
									llPatterns[i / 4][i % 4].setBackgroundResource(R.drawable.pattern_off);
								}

								v.setBackgroundResource(R.drawable.pattern_del);

								nWillDelete = v.getId() - patternID;
							}
						}
					}
				});

				llPatterns[i][j].setOnLongClickListener(new OnLongClickListener() {

					public boolean onLongClick(View v) {
						// If you want to making pattern, long click a
						// pattern layout.
						if (MainActivity.bEnablePatterns[v.getId() - patternID] == true) {
							bDeleteMode = true;

							drawAllPatterns();

							if (MainActivity.nTotalPattern < 16) {
								llPatterns[MainActivity.nTotalPattern / 4][MainActivity.nTotalPattern % 4]
										.setVisibility(View.INVISIBLE);
							}

							showToast("If you want to delete a pattern, just double click a pattern");
						}

						return true;
					}
				});
			}
		}

		// Draw all pattern view
		drawAllPatterns();
	}

	public static void drawAllPatterns() {

		for (int i = 0; i < 16; i++) {
			if (bDeleteMode == true) {
				llPatterns[i / 4][i % 4].setBackgroundResource(R.drawable.pattern_off);
			} else {
				llPatterns[i / 4][i % 4].setBackgroundResource(R.drawable.pattern_on);
			}
			llPatterns[i / 4][i % 4].setVisibility(View.INVISIBLE);
			tvPatternNum[i / 4][i % 4].setVisibility(View.INVISIBLE);
		}

		for (int i = 0; i < MainActivity.nTotalPattern; i++) {
			llPatterns[i / 4][i % 4].setVisibility(View.VISIBLE);
			tvPatternNum[i / 4][i % 4].setVisibility(View.VISIBLE);
		}

		if (MainActivity.nTotalPattern < 16) {
			llPatterns[MainActivity.nTotalPattern / 4][MainActivity.nTotalPattern % 4].setVisibility(View.VISIBLE);
			llPatterns[MainActivity.nTotalPattern / 4][MainActivity.nTotalPattern % 4]
					.setBackgroundResource(R.drawable.add);
		}
	}

	public static void drawPatterns(int nThisPattern) {
		if (MainActivity.bEnablePatterns[nThisPattern] == true) {
			tvNowPattern.setText((nThisPattern + 1) + " / 16");

			for (int i = 0; i < 16; i++) {
				for (int j = 0; j < 8; j++) {
					if ((MainActivity.nPatterns[nThisPattern][i] & MainActivity.DIGITS[j]) == MainActivity.DIGITS[j]) {
						llPads[j][i].setBackgroundColor(Color.argb(150, 77, 173, 255));
					} else {
						if (i % 4 == 0) {
							llPads[j][i].setBackgroundColor(Color.argb(80, 255, 255, 255));
						} else {
							llPads[j][i].setBackgroundColor(Color.argb(50, 255, 255, 255));
						}

					}
				}
			}
		}
	}

	public void resetPatterns() {
		for (int i = 0; i < 16; i++) {
			for (int j = 0; j < 16; j++) {
				MainActivity.nPatterns[i][j] = 0;
			}
		}

		drawPatterns(0);

		showToast("Clear all patterns!");
	}

	public void openAllPatterns() {
		llLeftBackground.setVisibility(View.INVISIBLE);
		llRightBackground.setVisibility(View.INVISIBLE);

		for (int i = 0; i < 8; i++) {
			llHorizontal[i].setVisibility(View.INVISIBLE);
		}

		llSecondBackground.setVisibility(View.VISIBLE);

		for (int i = 0; i < 4; i++) {
			llSecondHorizontal[i].setVisibility(View.VISIBLE);
		}

		drawAllPatterns();
	}

	public void closeAllPatterns(int nThisPattern) {
		llLeftBackground.setVisibility(View.VISIBLE);
		llRightBackground.setVisibility(View.VISIBLE);

		for (int i = 0; i < 8; i++) {
			llHorizontal[i].setVisibility(View.VISIBLE);
		}

		llSecondBackground.setVisibility(View.INVISIBLE);
		for (int i = 0; i < 4; i++) {
			llSecondHorizontal[i].setVisibility(View.INVISIBLE);
		}

		if (nThisPattern == -1) {
			nNowPattern = 0;
		} else {
			nNowPattern = nThisPattern;
		}

		drawPatterns(nNowPattern);
	}

	public void importPatterns(String sFileName) {
		try {
			String sData;
			String sHeader;
			String sBPM;
			String sEnabled;
			FileInputStream fi = openFileInput(sFileName);
			int nFileSize = fi.available();
			byte[] byData = new byte[nFileSize];

			if (fi.read(byData) != -1) {
				sHeader = new String(byData, 0, 7);
				if (sHeader.compareTo("beatit_") != 0) {
					showToast("Import failed! It isn't 'BeatIT(*.bti)' File.");
				}
			}

			sBPM = new String(byData, 7, 3);
			MainActivity.fBPM = Float.parseFloat(sBPM);

			sEnabled = new String(byData, 10, 16);

			MainActivity.nTotalPattern = 0;
			for (int i = 0; i < 16; i++) {
				if (sEnabled.charAt(i) == 'o') {
					MainActivity.bEnablePatterns[i] = true;
					MainActivity.nTotalPattern++;
				} else {
					MainActivity.bEnablePatterns[i] = false;
				}
			}

			sData = new String(byData, 26, nFileSize - 26);

			fi.close();

			int k = 0;
			int x = 0;
			int z = 0;
			int[] nTempPattern = new int[256];

			while (k < 16) {
				String sTemp = "";
				while (sData.charAt(x) != ',' && sData.charAt(x) != ';') {
					sTemp += sData.charAt(x++);
				}

				nTempPattern[z++] = Integer.parseInt(sTemp);

				if (sData.charAt(x) == ';') {
					x++;
					k++;

					continue;
				}
				x++;
			}

			z = 0;

			for (int i = 0; i < 16; i++) {
				for (int j = 0; j < 16; j++) {
					MainActivity.nPatterns[i][j] = nTempPattern[z++];
				}
			}

			showToast("Import success!");

			drawPatterns(nNowPattern);
			drawAllPatterns();

			MainActivity.nBeat = (int) (1000 / (MainActivity.fBPM / 15));
		} catch (Exception e) {
			showToast("Import failed...");
		}
	}

	public void extractPatterns(String sFileName, int nBPM) {
		try {
			String sBPM = "";
			String sPatterns = "";
			String sEnabled = "";

			if (nBPM / 100 == 0) {
				sBPM = String.valueOf(0);
			} else {
				sBPM = String.valueOf(nBPM / 100);
			}
			nBPM %= 100;
			if (nBPM / 10 == 0) {
				sBPM += String.valueOf(0);
			} else {
				sBPM += String.valueOf(nBPM / 10);
			}
			nBPM %= 10;
			if (nBPM == 0) {
				sBPM += String.valueOf(0);
			} else {
				sBPM += String.valueOf(nBPM);
			}

			for (int i = 0; i < 16; i++) {
				if (MainActivity.bEnablePatterns[i] == true) {
					sEnabled += "o";
				} else {
					sEnabled += "x";
				}
			}

			for (int i = 0; i < 16; i++) {
				for (int j = 0; j < 16; j++) {
					sPatterns += String.valueOf(MainActivity.nPatterns[i][j]);

					if (j == 15) {
						sPatterns += ";";
					} else {
						sPatterns += ",";
					}
				}
			}

			FileOutputStream fo = openFileOutput(sFileName + ".bti", Context.MODE_WORLD_READABLE);
			fo.write("beatit".getBytes());
			fo.write(("_" + sBPM).getBytes());
			fo.write(sEnabled.getBytes());
			fo.write(sPatterns.getBytes());
			fo.close();

			showToast("Extraction success!");
		} catch (Exception e) {

			showToast("Extract failed...");
		}

	}

	public void showToast(String s) {
		Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
	}

	@Override
	protected void onPause() {
		bDraw = false;

		super.onPause();
	}

	@Override
	protected void onResume() {
		bDraw = true;
		nNowPattern = 0;
		drawPatterns(nNowPattern);
		drawAllPatterns();

		if (bImported == true) {
			importPatterns(FileList.sFileName);

			// set a BPM
			SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);

			SharedPreferences.Editor edit = pref.edit();
			edit.putString("bpm", "" + (int) MainActivity.fBPM);
			edit.commit();

			Patterns.bImported = false;
		}

		for (int i = 0; i < 8; i++) {
			tvPads[i].setText(sSoundName[MainActivity.SOUNDIDS[i] - MainActivity.nSoundID]);
		}

		super.onResume();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (bDeleteMode == true) {
				bDeleteMode = false;

				drawAllPatterns();
			}
		}

		return super.onKeyDown(keyCode, event);
	}

}